package com.jeehentor.config.security;

import com.jeehentor.config.security.filter.JWTAuthenticationFilter;
import com.jeehentor.config.security.handler.MyAccessDeniedHandler;
import com.jeehentor.config.security.handler.MyAuthenticationEntryPoint;
import com.jeehentor.config.security.manager.DbUserDetailsManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * @Description : Security配置
 * @Author : wzd
 * @Date : 2024/4/9 14:40
 * @Version : 1.0
 **/
@Configuration  //标记此类为一个springboot的配置类
@EnableWebSecurity  //开启security基于web开发的安全机制
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final DbUserDetailsManager manager;

    private final MyAuthenticationEntryPoint authenticationEntryPointImpl;

    private final MyAccessDeniedHandler accessDeniedHandlerImpl;

    private final JWTAuthenticationFilter jwtTokenFilter;

    private final PasswordEncoder passwordEncoder;

    @Bean
    public AuthenticationManager authenticationManager() {
        //配置认证管理器，security框架默认不提供
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        //设置securityUserDetailService，告知security框架，按照指定的类进行身份校验
        daoAuthenticationProvider.setUserDetailsService(manager);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
        ProviderManager pm = new ProviderManager(daoAuthenticationProvider);
        return pm;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //将自定义的token认证过滤器加入到security-filterChian中，并指定其位置
        http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //关闭 防止客户端的 csrf（跨站伪造） 攻击行为 的能力
        // 从security过滤器链中撤出 CsrfFilter
        http.csrf(AbstractHttpConfigurer::disable);
        // 忽略授权的地址列表
        //TODO 从配置文件中读取
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers("/doc.html","/user/login","/v3/api-docs/**","/websocket/**"
                        ,"/swagger/**","/swagger-resources/**"," /swagger-ui.html","/swagger-ui/**","/webjars/**").permitAll()
                .requestMatchers(HttpMethod.OPTIONS).permitAll()
                .anyRequest().authenticated()
        );
        //自定义401、403返回结果
        http.exceptionHandling(cuse ->{
                    cuse.authenticationEntryPoint(authenticationEntryPointImpl)
                            .accessDeniedHandler(accessDeniedHandlerImpl);
                }
        );
        return http.build();
    }


}
